 package com.cartagena.financo.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.interceptor.multipart.UploadedFile;

import com.cartagena.financo.model.Term;
import com.cartagena.financo.model.Transaction;
import com.cartagena.financo.model.TransactionType;
import com.cartagena.financo.repository.TermRepository;
import com.cartagena.financo.repository.TransactionRepository;
import com.cartagena.financo.util.FloatingOFXTransactions;
import com.cartagena.ofx.model.OFXTransaction;
import com.cartagena.ofx.parser.OFXParser;
import com.cartagena.vraptor.extjs.ExtJSJson;
import com.cartagena.vraptor.extjs.ExtJSJson.ContentType;

@Resource
public class TermController { 
    
    private final Result result;
    private final TransactionRepository transactionRepository;
    private final TermRepository termRepository;
    private final FloatingOFXTransactions floatOfx;
    
    
    public TermController(Result result, TransactionRepository transactionRepository, TermRepository termRepository, FloatingOFXTransactions floatOfx) {
        this.result = result; 
        this.transactionRepository = transactionRepository;
        this.termRepository = termRepository;
        this.floatOfx = floatOfx;
    }
    
    @Post
    @Path("/term")
    public void save(Term term) {
        termRepository.add(term);
        
        List<OFXTransaction> floatingTerm = floatOfx.getTransactions(term.getText());
        for(OFXTransaction ofx : floatingTerm) {
            Transaction transaction = buildTransaction(ofx, term);
            transactionRepository.add(transaction);
        }
        
        this.floatOfx.remove(floatingTerm);
        
        this.result.use(ExtJSJson.class).from(term).success().serialize();
    }
    
    @Get
    @Path("/newterm")
    public void listAll() {
        Set<Term> newTerms = this.floatOfx.getNewterms();
        this.result.use(ExtJSJson.class).from(newTerms).success().serialize();
    }

    @Post
    @Path("/import")
    public void importOFX(UploadedFile file) {
        List<OFXTransaction> ofxTransactions = OFXParser.parse(file.getFile());
        
        Set<Term> newTerms = new HashSet<Term>();
        List<OFXTransaction> floatingTransactions = new ArrayList<OFXTransaction>();
        
        for(OFXTransaction ofx : ofxTransactions) {
            Term term = termRepository.loadByText(ofx.getDescription());            
            if(term != null) {
                Transaction transaction = buildTransaction(ofx, term);
                transactionRepository.add(transaction);
            } else {
                term = new Term();
                term.setText(ofx.getDescription());
                
                floatingTransactions.add(ofx);                
                newTerms.add(term);
            }
        }
        
        if(floatingTransactions.size() > 0) {
            floatOfx.setTransactions(floatingTransactions);
            floatOfx.setNewterms(newTerms);
        }
        
        
        this.result.use(ExtJSJson.class).from(newTerms, ContentType.TEXT).success().serialize();
    }
    
    private Transaction buildTransaction(OFXTransaction ofx, Term term) {
        Transaction transaction = new Transaction();
        transaction.setCategory(term.getCategory());
        transaction.setDate(ofx.getDate());
        transaction.setDescription(ofx.getDescription());
        transaction.setValue(BigDecimal.valueOf(Math.abs(ofx.getAmount())));
        transaction.setType(ofx.getAmount() < 0 ? TransactionType.DEBIT : TransactionType.CREDIT);

        
        return transaction;
    }

}
